/*
 * This netstream.cpp from ShowEQ, modified to work with EQEmu Source
 *
 *  ShowEQ Distributed under GPL
 *  http://www.sourceforge.net/projects/seq
 *
 *  Copyright 2004 Zaphod (dohpaz@users.sourceforge.net). 
 *  modified by erde (2009)
 */

#include "MemStream.h"

inline uint16 eqntohuint16(const uint8* data)
{
  return (uint16)((data[0] << 8) | data[1]);
}

inline int16 eqntohint16(const uint8* data)
{
  return (int16)((data[0] << 8) | data[1]);
}

inline  uint32 eqntohuint32(const uint8* data)
{
  return (uint32)((data[0] << 24) | (data[1] << 16) |
		    (data[2] << 8) | data[3]);
}

inline int32 eqntohint32(const uint8* data)
{
  return (int32)((data[0] << 24) | (data[1] << 16) |
		   (data[2] << 8) | data[3]);
}

inline uint16 eqtohuint16(const uint8* data)
{
  return *(uint16*)data;
}

inline int16 eqtohint16(const uint8* data)
{
  return *(int16*)data;
}

inline uint32 eqtohuint32(const uint8* data)
{
  return *(uint32*)data;
}

inline int32 eqtohint32(const uint8* data)
{
  return *(int32*)data;
}

MemStream::MemStream(const uint8* data, size_t length)
  : m_data(data),
    m_length(length)
{
  m_lastPos = &m_data[m_length];

  reset();
}
MemStream::~MemStream()
{
}

void MemStream::reset()
{
  // reset position to the end of the string
  m_pos = m_data;
}

uint8 MemStream::readUInt8()
{
  uint8 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 1)
  {
    // convert the data and increment past it
    val = *m_pos;
    m_pos++;
  }
  else 
    val = 0; // just return 0 if no data left

  return val;
}

int8 MemStream::readInt8()
{
  int8 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 1)
  {
    // convert the data and increment past it
    val = *(int8*)m_pos;
    m_pos++;
  }
  else 
    val = 0; // just return 0 if no data left

  return val;
}

uint16 MemStream::readUInt16()
{
  uint16 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 2)
  {
    // convert the data and increment past it
    val = eqntohuint16(m_pos);
    m_pos += 2;
  }
  else 
    val = 0; // just return 0 if no data left

  return val;
}

int16 MemStream::readInt16()
{
  int16 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 2)
  {
    // convert the data and increment past it
    val = eqntohint16(m_pos);
    m_pos += 2;
  }
  else
    val = 0; // just return 0 if no data left

  return val;
}

uint32 MemStream::readUInt32()
{
  uint32 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 4)
  {
    // convert the data and increment past it
    val = eqntohuint32(m_pos);
    m_pos += 4;
  }
  else 
    val = 0; // just return 0 if no data left

  return val;
}

int32 MemStream::readInt32()
{
  uint32 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 4)
  {
    // convert the data and increment past it
    val = eqntohint32(m_pos);
    m_pos += 4;
  }
  else
    val = 0; // just return 0 if no data left

  return val;
}

string MemStream::readText()
{
  // make sure there is data left
  if (m_pos < m_lastPos)
  {
    // note the starting position
    const uint8* startPos = m_pos;
    
    // search for the end of the NULL terminated string
    while ((*m_pos != '\0') && (m_pos < m_lastPos))
      m_pos++;
    
    size_t len = m_pos - startPos;

    // skip over trailing null
    if (m_pos < m_lastPos)
      m_pos++;
    
    // return the result as a string
	string tmp = (char*)startPos;
    return tmp;
  }
  else
    return string();
}

uint16 MemStream::readUInt16NC()
{
    uint16 val;

  // make sure there is enough data left
    if ((m_lastPos - m_pos) >= 2)
    {
    // convert the data and increment past it
        val = eqtohuint16(m_pos);
        m_pos += 2;
    }
    else 
        val = 0; // just return 0 if no data left

    return val;
}

uint32 MemStream::readUInt32NC()
{
  uint32 val;

  // make sure there is enough data left
  if ((m_lastPos - m_pos) >= 4)
  {
    // convert the data and increment past it
    val = eqtohuint32(m_pos);
    m_pos += 4;
  }
  else 
    val = 0; // just return 0 if no data left

  return val;
}

void MemStream::skipBytes(size_t byteCount)
{
  if (uint32(m_lastPos - m_pos) >= byteCount)
  {
    m_pos += byteCount;
  }
}
